/** 
 * Exemplar speichert Informationen von Medien z.B. den Barcode,  
 * ob es reserviert ist, ausgeliehen usw. Ausserdem wird die Position
 * Medium gespeichert.
 * 
 * Alle Methoden mit setze...() weisen einer Variablen einen Wert zu.
 * Alle get...() Methoden liefern den Wert der jeweiligen Variablen
 * zurueck. Die ist....() pruefen ob ein Wert gesetzt ist und es wird
 * true oder false zurueck gegeben.
 * 
 * Datei: Exemplar.java 		Autor: Simon Schindelmann 
 * Datum: 12.11.11                 	Version: 0.1
 * 
 */

package medienverwaltung;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import medienverwaltung.simulation.Uebersetzung;
import personenverwaltung.Ausleihe;
import personenverwaltung.Reservierung;

public class Exemplar implements Serializable
{
  private static final long serialVersionUID = -4921564651992245334L;
  //Speichert die aktuelle Sprache die verwendet wird.
  private Uebersetzung uebersetzung = Uebersetzung.gibSprache ();
  private EAN13 barcode;
  private Standort standort;
  private Medium medium;
  private int exemplarNr;
  private int regalId;
  private int etage;                            /* Regaletage         */
  private int abschnitt;                        /* Regalabschnitt     */
  private boolean ausgeliehen;
  private boolean reserviert;
  // Bewertung aufaddiert
  private int bewertungen;
  // Durchschnitt der Bewertungen
  private float bewertung;
  // Anzahl der Bewertungen
  private int anzahlBewertung;                  
  private boolean gesperrt;
  private  ArrayList<Reservierung> reservierungListe = 
    new ArrayList<Reservierung> ();
  Ausleihe ausleihe;
  Mediumverwalter mv = new Mediumverwalter ();

  public Exemplar (int ortId, Medium medium, int regalId, int etage,
      int abschnitt)
  {
    standort = standortSetzen (ortId);
    this.medium = medium;
    this.regalId = regalId;
    this.etage = etage;
    this.abschnitt = abschnitt;
    ausgeliehen = false;
    reserviert = false;
    gesperrt = false;
    bewertung = 0;
    anzahlBewertung = 0;
    bewertungen = 0;
    exemplarNr = setzeExemplarNr ();
    barcode = new EAN13 (this.medium.gibMediumId (), exemplarNr,
        standort.gibStandortId ());
  }

  
  /**
   * Hier wird das Exemplar in den Status augeliehen gesetzt.
   */
  public void ausleihen ()
  {
    ausgeliehen = true;
    mv.zustandSpeichern ();
  }


  /**
   * Hier wird das Exemplar in den Status reserviert gesetzt.
   */
  public void reservieren ()
  {
    reserviert = true;
    mv.zustandSpeichern ();
  }

  
  /**
   * Hier wird das Exemplar in den Status gesperrt versetzt.
   */
  public void sperren ()
  {
    gesperrt = true;
    mv.zustandSpeichern ();
  }


  /**
   * Prueft ob das Exemplar Ausgeliehen ist.
   * @return Es wird true zurueck gegeben wenn das Exemplar ausgeliehen
   * ist. Andernfalls false.
   */
  public boolean istAusgeliehen ()
  {
    return ausgeliehen;
  }

  
  /**
   * Prueft ob das Exemplar Ausgeliehen ist.
   * @return Es wird true zurueck gegeben wenn das Exemplar ausgeliehen
   * ist. andernfalls false.
   */
  public boolean istReserviert ()
  {
    return reserviert;
  }

  
  /**
   * Prueft ob das Exemplar gesperrt ist.
   * @return Es wird true zurueck gegeben wenn das Exemplar gesperrt
   * ist. andernfalls false.
   */
  public boolean istGesperrt ()
  {
    return gesperrt;
  }

  
  /**
   * Exemplar kann wieder ausgeliehen werden.
   */
  public void rueckgabe ()
  {
    ausgeliehen = false;
    mv.zustandSpeichern ();
  }

  
  /**
   * Reservierung wird hier wieder aufgehoben.
   */
  public void reservierungAufheben ()
  {
    reserviert = false;
    mv.zustandSpeichern ();
  }

  
  /**
   * Exemplar wird hier entsperrt.
   */
  public void entsperren ()
  {
    gesperrt = false;
    mv.zustandSpeichern ();
  }


  /**
   * Bewertet ein Exemplar in der Bibliothek
   * @param bewertung liefert eine Zahl zwischen 0 und 100 fuer die
   * Bewertung
   */
  public void bewerten (String bewertung)
      throws AusserhalbdesDefiniertenBereichsAusnahme
  {
    int temp = DatumParser.stringZuInteger (bewertung);
    if (temp >= 0 && temp <= 100)
    {
      bewertungen = bewertungen + temp;
      anzahlBewertung++;
      this.bewertung = (float) bewertungen / anzahlBewertung;
    }
    else
    {
      throw new AusserhalbdesDefiniertenBereichsAusnahme (
          uebersetzung.lokal
              .gibUebersetzung ("Wert ausserhalb des definierten " +
              		              "Bereichs"));
    }
    mv.zustandSpeichern ();
  }

  
  /**
   * Gibt die Bewertung zurueck.
   * @return Bewertung des Exemplars.
   */
  public float gibBewertungen ()
  {
    return bewertung;
  }


  /**
   * Gibt die EAN des Exemplars zurueck.
   * @return EAN des Exemplars.
   */
  public EAN13 gibBarcode ()
  {
    return barcode;
  }

  
  /**
   * Gibt den Standort des Exemplars zurueck.
   * @return Standort des Exemplars.
   */
  public Standort gibStandort ()
  {
    return standort;
  }


  /**
   * Gibt die Exemplarnummer des Exemplars zurueck.
   * @return Exemplarnummer
   */
  public int gibExemplarNr ()
  {
    return exemplarNr;
  }


  /**
   * Gibt RegalId des Exemplars zurueck.
   * @return RegalId des Exemplars.
   */
  public int gibRegalId ()
  {
    return regalId;
  }

  
  /**
   * Gibt die RegalEtagennummer zurueck in der das Exemplar steht.
   * @return RegalEtagennummer des Exemplars.
   */
  public int gibEtage ()
  {
    return etage;
  }


  /**
   * Gibt die Regalabschnittsnummer zurueck wo das Exemplar steht.
   * @return Regalabschnittsnummer des Exemplars.
   */
  public int gibAbschnitt ()
  {
    return abschnitt;
  }

  
  /**
   * Gibt das Medium des Exemplars zurueck.
   * @return Medium des Exemplars.
   */
  public Medium gibMedium ()
  {
    return medium;
  }


  /**
   * Setzt die ExemplarNr indem geguckt wird ob das selbe Medium schon
   * in der Bibliothek vorhanden ist. Wenn das Medium 2 mal schon in der
   * Bibliothek steht wird die ExemplarNr dann auf 3 gesetzt da es dann
   * das 3. Exemplar ist.
   * @return gibt die ExemplarNr zurueck.
   */
  private int setzeExemplarNr ()
  {
    // Anzahl der Exemplar 
    int i = 0;
    Mediumverwalter mv = new Mediumverwalter ();
    HashMap<EAN13, Exemplar> liste = new HashMap<EAN13, Exemplar> ();
    liste = mv.gibExemplarListe ();

    for (Exemplar e : liste.values ())
    {
      if (e.gibMedium ().gibMediumId () == medium.gibMediumId ())
      {
        i = i + 1;
      }
    }
    i = i + 1;
    return i;
  }

  
  /**
   * Gibt eine Liste mit den Reservierungen zurueck.
   * @return ArrayList mit Reservierungen.
   */
  public ArrayList<Reservierung> gibReservierungen ()
  {
    return reservierungListe;
  }


  /**
   * Fuegt dem Exemplar eine Reservierung hinzu.
   * @param r
   */
  public void reservierungHinzufuegen (Reservierung r)
  {
    reservierungListe.add (r);
    mv.zustandSpeichern ();
  }

  
  /**
   * Loescht eine Reservierung aus der Reservierungsliste.
   * @param index Index der Reservierung die geloescht werden soll.
   */
  public void reservierungLoeschen (int index)
  {
    reservierungListe.remove (index);
    mv.zustandSpeichern ();
  }

  
  /**
   * Gibt die Ausleihe zurueck.
   * @return Ausleihe.
   */
  public Ausleihe gibAusleihe ()
  {
    return ausleihe;
  }


  /**
   * Hier wird die Ausleihe gesetzt.
   * @param a Ausleihe.
   */
  public void setzeAusleihe (Ausleihe a)
  {
    ausleihe = a;
    mv.zustandSpeichern ();
  }


  /**
   * Guckt ob es diesen Standort schon gibt. Falls nicht wird dieser
   * Standort angelegbt. 
   * @param name Name des Standortes.
   * @return das Standortobjekt.
   */
  private Standort standortSetzen (int ortId)
  {
    Standortverwalter sv = new Standortverwalter ();
    for (Standort s : sv.gibStandortListe ())
    {
      if (s.gibStandortId () == ortId)
      {
        return s;
      }
    }
    return null;
  }
  
  
  /**
   * Prueft ob das Exemplar ausgeliehen werden kann. Wenn das Exemplar
   * gesperrt ist oder shcon ausgeliehen ist kann es nicht ausgeliehen
   * werden
   * @return gibt true zurueck wenn es Auseihbar ist andernfalls false
   */
  public boolean istAusleihbar ()
  {
    if(istAusgeliehen () == true || istGesperrt () == true)
    {
      return false;
    }
    else
    {
      return true;
    }  
  }
}